package cn.miju.unionpay.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.miju.common.content.CodeMessage;
import cn.miju.common.exception.ValidateException;
import cn.miju.common.util.OkHttpUtil;
import cn.miju.common.util.ValidationUtil;
import cn.miju.unionpay.constant.UnionPayConstant;
import cn.miju.unionpay.model.RefundRequest;
import cn.miju.unionpay.model.RefundResponse;
import cn.miju.unionpay.model.UnionPayRequest;
import cn.miju.unionpay.model.UnionPayResponse;
import cn.miju.unionpay.properties.UnionPayProperties;
import cn.miju.unionpay.request.UnionPayRefundOrderReq;
import cn.miju.unionpay.response.UnionPayBaseResp;
import cn.miju.unionpay.response.UnionPayRefundOrderResp;
import cn.miju.unionpay.util.UnionPaySignUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;

/**
 * <pre>
 * 订单退款
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-15 22:39
 */
@Slf4j
@Component
public class UnionPayRefundOrderHandler extends AbstractUnionPayHandler<UnionPayRefundOrderReq, UnionPayRefundOrderResp> {
    /**
     * 可选返回参数(如果接口所需参数不满足需求，可按照官方接口文档，原样传入对应参数)
     */
    private Set<String> optionalRespParams;
    @Override
    public RefundRequest beforeRequest(UnionPayRefundOrderReq req) {
        ValidationUtil.validate(req);
        if (StringUtils.isBlank(req.getOutRefundNo()) && StringUtils.isBlank(req.getTradeNo())) {
            throw new ValidateException("传入原支付商户订单号和原支付银联交易号不能同时为空");
        }
        UnionPayProperties unionPayProperties = req.getUnionPayProperties();
        UnionPayRequest request = super.beforeRequest(req);
        request.setTxnType(UnionPayConstant.TxnType.REFUND);
        request.setTxnSubType(UnionPayConstant.TxnSubType.DEFAULT);
        request.setBizType(UnionPayConstant.BizType.DEFAULT);
        request.setChannelType(UnionPayConstant.ChannelType.MOBILE);
        request.setCurrencyCode(UnionPayConstant.CURRENCY_CODE);
        request.setMerId(unionPayProperties.getMerchantNo());
        RefundRequest refundRequest = BeanUtil.copyProperties(request, RefundRequest.class);
        refundRequest.setOrderId(req.getOutRefundNo());
        refundRequest.setTxnAmt(String.valueOf(req.getRefundAmount()));
        refundRequest.setOrigOrderId(req.getOutTradeNo());
        refundRequest.setOrigQryId(req.getTradeNo());
        refundRequest.setOrigTxnTime(req.getPayCreateTime());
        refundRequest.setBackUrl(StringUtils.isBlank(req.getBackUrl()) ? UnionPayConstant.DEFAULT_BACK_URL : req.getBackUrl());
        optionalRespParams = req.getOptionalRespParams();
        super.setOptionalReqParams(refundRequest, req.getOptionalReqParams());
        return refundRequest;
    }

    /**
     * 核心执行
     *
     * @param req {@link UnionPayRefundOrderReq}
     * @return {@link UnionPayRefundOrderResp}
     */
    @Override
    public UnionPayRefundOrderResp doPlan(UnionPayRefundOrderReq req) {
        UnionPayProperties unionPayProperties = req.getUnionPayProperties();
        RefundRequest request = this.beforeRequest(req);
        // 签名
        Map<String, String> param = JSONObject.parseObject(JSONObject.toJSONString(request), Map.class);
        UnionPaySignUtil.sign(param, unionPayProperties.getSignCertPath(), unionPayProperties.getSignCertPwd());
        String reqParam = UnionPaySignUtil.createLinkString(param, false, true, StandardCharsets.UTF_8.toString());
        // 请求
        log.info("API--退货类（退货）--> Request：{}", reqParam);
        String result = OkHttpUtil.doPost(unionPayProperties.getServiceUrl(), reqParam);
        log.info("API--退货类（退货）--> Response：{}", result);
        if (StringUtils.isBlank(result)) {
            return UnionPayRefundOrderResp.builder().code(CodeMessage.FAIL.getCode()).msg("响应数据为空").build();
        }
        RefundResponse response = JSONObject.parseObject(JSONObject.toJSONString(UnionPaySignUtil.readLinkStr(result)), RefundResponse.class);
        return this.afterResponse(response);
    }

    /**
     * 响应参数后置处理
     *
     * @param resp 响应参数
     * @return 结果
     */
    @Override
    public UnionPayRefundOrderResp afterResponse(UnionPayResponse resp) {
        UnionPayBaseResp baseResp = UnionPayBaseResp.preBuilder(CodeMessage.FAIL);
        RefundResponse response = (RefundResponse) resp;
        if (StringUtils.isNotBlank(response.getRespMsg())) {
            baseResp.setMsg(response.getRespMsg());
        }
        if (response.isSuccess()) {
            baseResp = UnionPayBaseResp.preBuilder(CodeMessage.SUCCESS);
            baseResp.setOptionalRespParams(super.getOptionalRespParams(response, optionalRespParams));
        }
        UnionPayRefundOrderResp unionPayRefundOrderResp = BeanUtil.copyProperties(baseResp, UnionPayRefundOrderResp.class);
        unionPayRefundOrderResp.setTradeNo(response.getQueryId());
        return unionPayRefundOrderResp;
    }
}
